//
//  ActionScript.swift
//  Urso
//
//  Created by Cosmetic Cygia on 2024/6/21.
//

import Foundation
import SwiftUI

protocol DeviceDescriptorBase {
    
    var deviceType: Int? { get }
    
    var alias: String? { get }
    
    var deviceClass: Any? { get }
    
    init(deviceType: Int, alias: String, deviceClass: Any)
}

class DeviceDescriptor: DeviceDescriptorBase {
    var deviceType: Int?
    
    var alias: String?
    
    var deviceClass: Any?
    
    required init(deviceType: Int, alias: String, deviceClass: Any) {
        self.deviceType = deviceType
        self.alias = alias
        self.deviceClass = deviceClass
    }

}
class VariablePool<T> {
    
    var vars: [String: T] = [:]
    
    init() {}
    
    func setVar(name: String, value: T) {
            vars[name] = value
           
    }
    
    func getVar(name: String) -> T? {
        return vars[name] // This will return nil if the key does not exist
    }
}

class ActionScript: ObservableObject   {
    
    @Published var currentScript: String = ""
    
    var onSendIPhoneMessage: ((_ alias: String, _ message: String) -> Int)?
    
    var rawScripts: [String] = []
    
    var deviceDescriptors: [DeviceDescriptor] = []
    
    var varBools: VariablePool<Bool> = VariablePool()
    var stopFlag: Bool = false
    var pauseFlag: Bool = false
    var pauseAllowFlag: Bool = false
    var pauseInterval: Double = 0.02
    // var _scripts: [[String]] = []
    
    var uuid: String = ""
    
    @Published var scripts: [(name: String, value: [String])] = []
    var funcs: [(name: String, value: [String])] = []
    
    init() {
    }
    
    func loadScripts(path: URL) {
        self.rawScripts = getContent(path: path)
        closeAllDevices()
        deviceDescriptors = []
        scripts = []
        funcs = []
        decomposeScript()
    }
    
    func loadScripts(fileContents: String) {
        
        self.rawScripts = getContent(fileContents: fileContents)
        
        scripts = []
        funcs = []
        closeAllDevices()
        deviceDescriptors = []
        decomposeScript()
    }
    
    func getContent(fileContents: String) -> [String] {
        // Process the file content
        
        ELog.d(String(describing: type(of: self)),#function, fileContents, #line)
        // Split the string into an array of strings based on line breaks
        var rows = fileContents.components(separatedBy: .newlines)
        
        // Remove empty or whitespace-only rows
        rows = rows.filter { !$0.trimmingCharacters(in:     .whitespacesAndNewlines).isEmpty }
        
        return rows
    }
    
    func getContent(path: URL) -> [String] {
        do {
            let fileData = try Data(contentsOf: path)
            if let fileContents = String(data: fileData, encoding: .utf8) {
                return getContent(fileContents: fileContents)
            } else{
                // Unable to decode file data as UTF-8 string
                
                ELog.e(String(describing: type(of: self)),#function, "Error: Unable to decode file data", #line)
            }
        } catch {
            // Handle the case when reading the file fails
            ELog.e(String(describing: type(of: self)),#function, "Failed to read the file: \(error)", #line)
            return []
        }
        return []
    }
    
    func getDevices(alias: String) -> [DeviceDescriptor] {
        return self.deviceDescriptors.filter { deviceDescriptor in
            deviceDescriptor.alias == alias
        }
    }
    
    func decomposeScript() {

        scripts.removeAll()
        
        var thisScript: [String] = []
        var thisName: String = ""
        
        var rowCount: Int = 0
        
        var isScript = false
        
        for script in self.rawScripts {
            if (script.starts(with: "Button(") || script.starts(with: "Func(")) {
                let operators: [String] = analyzeString(script) ?? []
                
                if (operators.count == 2) {
                    if (operators[0] == "Button") {
                        if (rowCount != 0) {
                            if (isScript) {
                                scripts.append((name: thisName, value: thisScript))
                            } else {
                                funcs.append((name: thisName, value: thisScript))
                            }
                        }
                        isScript = true
                        thisName = operators[1]
                        thisScript.removeAll()
                    }
                    if (operators[0] == "Func") {
                        if (rowCount != 0) {
                            if (isScript) {
                                scripts.append((name: thisName, value: thisScript))
                            } else {
                                funcs.append((name: thisName, value: thisScript))
                            }
                        }
                        isScript = false
                        thisName = operators[1]
                        thisScript.removeAll()
                    }
                }
            } else {
                thisScript.append(script)
            }
            rowCount += 1
            if (rowCount == self.rawScripts.count) {
                if (thisScript.count != 0) {
                    if (isScript) {
                        scripts.append((name: thisName, value: thisScript))
                    } else {
                        funcs.append((name: thisName, value: thisScript))
                    }
                }
            }
        }
        ELog.d(String(describing: type(of: self)),#function, self.scripts.count.description, #line)
    }
    
    //MARK:  家在外部指令！！
    func runScript(scripts: [String]) -> String {
        
        var rowCount = 0
        
        let iPhoneManager = IPhoneManager()
        
        let timeoutInterval: Double = 5
        let dispatchGroup = DispatchGroup()
        
        for script in scripts {
            
            if (stopFlag) {
                stopFlag = false
                return "User stopped in row \(rowCount): \n\(script)\n"
            }
            
            currentScript = "Row \(rowCount): \(script)"
            PavaoManager.instance.saveLog(logLevel: .debug, logContent: "ActionScript: Running \(currentScript)")
            rowCount += 1
            
        
            
            let operators: [String] = analyzeString(script) ?? []
            print(operators)
            if (operators == []) {
                //      return "Script error in row \(rowCount): \n\(script)\n"
            } else {
                switch (operators[0]) {
                case "IKun":
                    if let index = Int(operators[1]) {
                        iKunSound.playIKun(index: index)
                    }
                    
                break
                case "Stop":
                    if (operators.count != 2) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    stopFlag = true
                break
                
                case "WhileDITrue":
                    
                        
                        if (operators.count != 4) {
                            return  "Parameters not match in row \(rowCount): \n\(script)\n"
                        }
                        guard let point = Int(operators[2]) else {
                            return "Error point in row \(rowCount): \n\(script)\n"
                        }
                        guard let station = Int(operators[3]) else {
                            return "Error station in row \(rowCount): \n\(script)\n"
                        }
                        let devices = getDevices(alias: operators[1])
                        switch (devices.count) {
                        case 0:
                            return "Device not found in row \(rowCount): \n\(script)\n"
                        case 1:
                            
                            var value = (devices.first?.deviceClass as! TcpIoManager).getDI(point: point, station: station)
                            while (!value) {
                                if (stopFlag) {
                                    
                                    stopFlag = false
                                    return "Parameters error in row \(rowCount): \n\(script)\n"
                                }
                                value = (devices.first?.deviceClass as! TcpIoManager).getDI(point: point, station: station)
                              //  print("TV: ", value)
                                Thread.sleep(forTimeInterval: TimeInterval(pauseInterval))
                            }
                            break
                        default:
                            return "Device duplicated in row \(rowCount): \n\(script)\n"
                        }
                        break
                case "AllowPause":
                    
                        if (operators.count != 2) {
                            return "Parameters error in row \(rowCount): \n\(script)\n"
                        }
                    pauseAllowFlag = (operators[1] == "1")
                    break
                case "Pause":
                        if (operators.count != 2) {
                            return "Parameters error in row \(rowCount): \n\(script)\n"
                        }
                    
                    if (pauseAllowFlag) {
                        pauseFlag = true
                        while (pauseFlag) {
                            
                                if (stopFlag) {
                                    
                                    stopFlag = false
                                    return "Parameters error in row \(rowCount): \n\(script)\n"
                                }
                            Thread.sleep(forTimeInterval: TimeInterval(pauseInterval))
                        }
                    }
                    
                    break
                case "Unpause":
                    
                        if (operators.count != 2) {
                            return "Parameters error in row \(rowCount): \n\(script)\n"
                        }
                    pauseFlag = false
                    
                    break
                    
                case "Not":
                    if (operators.count != 3) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name1 = operators[1]
                    let name2 = operators[2]
                    if let value = varBools.getVar(name: name1) {
                        
                        varBools.setVar(name: name2, value: !value)
                    } else {
                        
                        return "Variable \(name1) not found in row \(rowCount): \n\(script)\n"
                    }
                    break
                
                    
                case "And":
                    if (operators.count != 4) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name1 = operators[1]
                    let name2 = operators[2]
                    let name3 = operators[3]
                    if let value1 = varBools.getVar(name: name1) {
                        if let value2 = varBools.getVar(name: name2) {
                            
                            varBools.setVar(name: name3, value: value1 && value2)
                        } else {
                            
                            return "Variable \(name2) not found in row \(rowCount): \n\(script)\n"
                        }
                    } else {
                        
                        return "Variable \(name1) not found in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "Or":
                    if (operators.count != 4) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name1 = operators[1]
                    let name2 = operators[2]
                    let name3 = operators[3]
                    if let value1 = varBools.getVar(name: name1) {
                        if let value2 = varBools.getVar(name: name2) {
                            
                            varBools.setVar(name: name3, value: value1 || value2)
                        } else {
                            
                            return "Variable \(name2) not found in row \(rowCount): \n\(script)\n"
                        }
                    } else {
                        
                        return "Variable \(name1) not found in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "For":
                    
                    if (operators.count != 3) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[1]
                    if let times = Int(operators[2]) {
                        if (times <= 0) {
                            return "Times must > 0 in row \(rowCount): \n\(script)\n"
                        }
                        
                        if let funcFound = funcs.first(where: { $0.name == name }) {
                            for _ in 0..<times {
                                let result = runScript(scripts: funcFound.value)
                                if (result != "") {
                                    return result
                                }
                            }
                        } else {
                            return "FUNC \(name) not found in row \(rowCount): \n\(script)\n"
                        }
                    } else {
                        return "Times error in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "If":
                    
                    if (operators.count != 4) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[1]
                    let value = varBools.getVar(name: name)
                    if (value == nil) {
                        return "Value error in row \(rowCount): \n\(script)\n"
                    } else {
                        var funcTrue: (name: String, value: [String])?
                        var funcFalse: (name: String, value: [String])?
                        
                        if let foundTrue = funcs.first(where: { $0.name == operators[2] }) {
                            funcTrue = foundTrue
                        } else {
                            return "FUNC \(operators[2]) not found in row \(rowCount): \n\(script)\n"
                        }
                        
                        if let foundFalse = funcs.first(where: { $0.name == operators[3] }) {
                            funcFalse = foundFalse
                        } else {
                            return "FUNC \(operators[3]) not found in row \(rowCount): \n\(script)\n"
                        }
                        
                        if value! {
                            let result = runScript(scripts: funcTrue!.value)
                            if (result != "") {
                                return result
                            }
                        } else {
                            let result = runScript(scripts: funcFalse!.value)
                            if (result != "") {
                                return result
                            }
                        }
                    }
                    
                    break
                case "Sync":
                    
                    if (operators.count != 2) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[1]
                    if let foundFunc = funcs.first(where: { $0.name == name }) {
                        
                        let result = runScript(scripts: foundFunc.value)
                            if (result != "") {
                                return result
                            }
                    } else {
                        return "FUNC \(name) not found in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "Async":
                    
                    if (operators.count != 2) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[1]
                    if let foundFunc = funcs.first(where: { $0.name == name }) {
                        let group = DispatchGroup()
                        
                        var asyncResult: String = ""
                        let asyncQueue = DispatchSerialQueue(label: name, qos: .userInteractive)
                        asyncQueue.async(group: group) {
                            asyncResult = self.runScript(scripts: foundFunc.value)
                            
                        }
                        
                        group.notify(queue: asyncQueue, execute: {
                            if (asyncResult != "") {
                                print(asyncResult)
                               // return asyncResult
                            }
                        })
                    } else {
                        return "FUNC \(name) not found in row \(rowCount): \n\(script)\n"
                    }
                    break
                    // MARK: 0 Sleep
                case "Sleep":
                    if (operators.count != 2) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    Thread.sleep(forTimeInterval: TimeInterval(Double(operators[1])!))
                    break
                    // MARK: 1 AddDevicev
                case "ClearAllDevice":
                    
                        if (operators.count != 2) {
                            return "Parameters error in row \(rowCount): \n\(script)\n"
                        }
                    closeAllDevices()
                    deviceDescriptors = []
                    break
                case "AddTcpDevice":
                    if (operators.count != 5) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    guard let deviceType: Int = Int(operators[1]) else {
                        return "Unknown device type in row \(rowCount): \n\(script)\n"
                    }
                    guard let port: Int = Int(operators[4]) else {
                        return "Error port in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[2])
                    if (!devices.isEmpty) {
                        break
                    }
                    switch (deviceType) {
                    case 10001:
                        deviceDescriptors.append(DeviceDescriptor(deviceType: deviceType, alias: operators[2], deviceClass: InovanceRobotController(ipAddress: operators[3], port: port)))
                        break
                    case 20001:
                        
                        deviceDescriptors.append(DeviceDescriptor(deviceType: deviceType, alias: operators[2], deviceClass: OptFlashLightSourceController(ipAddress: operators[3], port: port)))
                        break
                    case 20002:
                        
                        deviceDescriptors.append(DeviceDescriptor(deviceType: deviceType, alias: operators[2], deviceClass: OptPermanentLightSourceController(ipAddress: operators[3], port: port)))
                        break
                    case 40001:
                        deviceDescriptors.append(DeviceDescriptor(deviceType: deviceType, alias: operators[2], deviceClass: TcpIoManager(ipAddress: operators[3], port: port)))
                        break
                    default:
                        return "Unknown device type in row \(rowCount): \n\(script)\n"
                    }
                    break
                    // MARK: 1.2 AddSerialDevice
                case "AddSerialDevice":
                    if (operators.count < 4) {
                        return "Parameters error in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[2])
                    if (!devices.isEmpty) {
                        break
                    }
                    var baudRate = 9600
                    
                    if (operators.count == 5) {
                        guard var baudRate_ = Int(operators[4]) else {
                            
                                return "Bad Baudrate in row \(rowCount): \n\(script)\n"
                        }
                        baudRate = baudRate_
                    }
                    guard let deviceType: Int = Int(operators[1]) else {
                        return "Unknown device type in row \(rowCount): \n\(script)\n"
                    }
                    switch (deviceType) {
                    case 30001:
                        deviceDescriptors.append(DeviceDescriptor(deviceType: deviceType, alias: operators[2], deviceClass: SerialMotorManager(motorName: operators[3], baudRate: baudRate)))
                        break
                    default:
                        return "Unknown device type in row \(rowCount): \n\(script)\n"
                        
                    }
                    break
                    
                    // MARK: 2 MotorControl
                    // MARK: 2.1 Enable Motor
                case "SMEnable":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        switch ((devices.first?.deviceClass as! SerialMotorManager).enableMotor(channel: UInt8(channel))) {
                        case .ok:
                            break
                        case .error:
                            return "Motor error in row \(rowCount): \n\(script)\n"
                        case .timeout:
                            return "Motor timeout in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    // MARK: 2.2 Disable Motor
                case "SMDisable":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch ( (devices.first?.deviceClass as! SerialMotorManager).disableMotor(channel: UInt8(channel))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "SMWait":
                    if (operators.count != 4) {
                        return "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let timeout: Int = Int(operators[3]) else {
                        return "Error timeout in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        switch( (devices.first?.deviceClass as! SerialMotorManager).waitForStop(channel: UInt8(channel), timeout: Double(timeout))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout: 
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "SMRelativelyMove":
                    if (operators.count != 3) {
                        return "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch( (devices.first?.deviceClass as! SerialMotorManager).relativelyMove(channel: UInt8(channel))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "SMSetAcc":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let acc: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch( (devices.first?.deviceClass as! SerialMotorManager).setAcc(channel: UInt8(channel), acc: Int32(acc))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "SMSetDcc":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let dcc: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        switch( (devices.first?.deviceClass as! SerialMotorManager).setDcc(channel: UInt8(channel), dcc: Int32(dcc))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "SMSetSteps":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let step: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch( (devices.first?.deviceClass as! SerialMotorManager).setSteps(channel: UInt8(channel), steps: Int32(step))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "SMSetSpeed":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let speed: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch( (devices.first?.deviceClass as! SerialMotorManager).setSpeed(channel: UInt8(channel), speed: Int32(speed))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "SMHome":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let trigger: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                       switch( (devices.first?.deviceClass as! SerialMotorManager).homeMotor(channel: UInt8(channel), trigger: UInt8(trigger))) {
                       case .ok:
                           break
                       case .error:
                           return "Motor error in row \(rowCount): \n\(script)\n"
                       case .timeout:
                           return "Motor timeout in row \(rowCount): \n\(script)\n"
                       }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break 
                case "SMSetAsServo":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let value: Int = Int(operators[3]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        (devices.first?.deviceClass as! SerialMotorManager).setAsServo(channel: UInt8(channel), isServo: value == 1)
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    // MARK: 3 LightSources
                    
                case "OptFLSSetPulseWidth":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let pulseWidth: Int = Int(operators[3]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! OptFlashLightSourceController).setPulseWidth(channel: UInt8(channel), pulseWidth: pulseWidth) {isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Light source controller communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Light source controller communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "OptFLSTrigger":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! OptFlashLightSourceController).trigger(channel: UInt8(channel)) {isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Light source controller communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Light source controller communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "OptPLSSetLightValue":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let value: Int = Int(operators[3]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! OptPermanentLightSourceController).setLedValue(channel: UInt8(channel), value: value) {isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Light source controller communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Light source controller communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "OptPLSSetStatus":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let channel: Int = Int(operators[2]) else {
                        return "Error channel in row \(rowCount): \n\(script)\n"
                    }
                    guard let status: Int = Int(operators[3]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! OptPermanentLightSourceController).setLed(channel: UInt8(channel), status: (status == 1)) {isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Light source controller communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Light source controller communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    // MARK: 4 ROBOT
                    
                case "IR6GetPermit":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).getPermit {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "IR6GetPermitForcibly":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                  //      DispatchQueue.global().asyncAndWait {
                        
                            (devices.first?.deviceClass as! InovanceRobotController).getPermitForcibly {  errorCode, isSuccess in
                                isSuccuss_ = isSuccess
                                dispatchGroup.leave()
                        }
                        
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "IR6RemovePermit":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).removePermit {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6Login":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let mode: Int = Int(operators[2]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).login(mode: mode, password: operators[3]) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6Logout":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).logout {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6ResetSystemError":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).resetSystemError {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                    
                case "IR6SetEmergencyStatus":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let status = Int(operators[2]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).setEmergencyStopStatus(status: (status == 1)) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6SetMotorStatus":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let status = Int(operators[2]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).setMotorStatus(status: (status == 1)) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "IR6SetDsmodeStatus":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let status = Int(operators[2]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).setDsmodeStatus(status: status) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6SetDo":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let point = Int(operators[2]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    guard let status = Int(operators[3]) else {
                        
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).setDo(point: point, status: (status == 1)) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "IR6GoHome0":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).goHome0 {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "IR6MovJGP":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let point = Int(operators[2]) else {
                        
                        return "Error point in row \(rowCount): \n\(script)\n"
                    }
                    guard let vel = Int(operators[3]) else {
                        
                        return "Error velocity in row \(rowCount): \n\(script)\n"
                    }
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        
                        dispatchGroup.enter()
                        var isSuccuss_: Bool = false
                        (devices.first?.deviceClass as! InovanceRobotController).movJGP(point: point, vel: vel, accuracy: 0) {errorCode, isSuccess in
                            isSuccuss_ = isSuccess
                            dispatchGroup.leave()
                        }
                        switch dispatchGroup.wait(timeout: .now() + timeoutInterval) {
                        case .success:
                            
                            if (!isSuccuss_) {
                                return "Robot communication failure in row \(rowCount): \n\(script)\n"
                            }
                            break
                        case .timedOut:
                            
                            return "Robot communication time out in row \(rowCount): \n\(script)\n"
                        }
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "iPhoneCapture":
                    if (operators.count != 5) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let volver = Int(operators[3]) else {
                        
                        return "Error volver in row \(rowCount): \n\(script)\n"
                    }
                    
                    let uuid_ = (operators[4] == "") ? uuid: operators[4]
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageCameraControl(trigger: true, formula: operators[2], volver: (volver == 1), uuid: uuid_ ))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneBlink":
                    if (operators.count != 2) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageBlink())) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetExpoTime":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let value = Float(operators[2]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetExpoTime(expoTime: value))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetIso":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let value = Float(operators[2]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetIso(iso: value))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetEv":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let value = Float(operators[2]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetEv(ev: value))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetZoom":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let value = Float(operators[2]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetZoom(zoom: value))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetFlash":
                    if (operators.count != 3) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let value = Float(operators[2]) else {
                        return "Error value in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetFlash(trigger: value == 1))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "iPhoneSetFocus":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let x = Float(operators[2]) else {
                        return "Error x in row \(rowCount): \n\(script)\n"
                    }
                    guard let y = Float(operators[3]) else {
                        return "Error y in row \(rowCount): \n\(script)\n"
                    }
                    switch (onSendIPhoneMessage!(operators[1], iPhoneManager.messageSetFocus(x: CGFloat(x), y: CGFloat(y)))) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                    
                case "SetDO":
                    if (operators.count != 5) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    
                    guard let point = Int(operators[2]) else {
                        return "Error point in row \(rowCount): \n\(script)\n"
                    }
                    guard let station = Int(operators[4]) else {
                        return "Error station in row \(rowCount): \n\(script)\n"
                    }
                    var value = varBools.getVar(name: operators[3])
                    if (value == nil) {
                        value = operators[3] == "1"
                    }
                    
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        (devices.first?.deviceClass as! TcpIoManager).SetDO(point: point, status: value!, station: station)
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "SetAllDO":
                    if (operators.count != 4) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    
                    guard let status = UInt16(operators[2]) else {
                        return "Error status in row \(rowCount): \n\(script)\n"
                    }
                    guard let station = Int(operators[3]) else {
                        return "Error station in row \(rowCount): \n\(script)\n"
                    }
                    
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        (devices.first?.deviceClass as! TcpIoManager).SetAllDO(status: status,station: station)
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                case "GetDO":
                    
                    if (operators.count != 5) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let point = Int(operators[2]) else {
                        return "Error point in row \(rowCount): \n\(script)\n"
                    }
                    guard let station = Int(operators[4]) else {
                        return "Error station in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[3]
                    varBools.setVar(name: name, value: false)
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        varBools.setVar(name: name, value:  (devices.first?.deviceClass as! TcpIoManager).getDO(point: point, station: station))
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                    
                case "GetDI":
                    
                    if (operators.count != 5) {
                        return  "Parameters not match in row \(rowCount): \n\(script)\n"
                    }
                    guard let point = Int(operators[2]) else {
                        return "Error point in row \(rowCount): \n\(script)\n"
                    }
                    guard let station = Int(operators[4]) else {
                        return "Error station in row \(rowCount): \n\(script)\n"
                    }
                    let name = operators[3]
                    varBools.setVar(name: name, value: false)
                    let devices = getDevices(alias: operators[1])
                    switch (devices.count) {
                    case 0:
                        return "Device not found in row \(rowCount): \n\(script)\n"
                    case 1:
                        varBools.setVar(name: name, value:  (devices.first?.deviceClass as! TcpIoManager).getDI(point: point, station: station))
                        break
                    default:
                        return "Device duplicated in row \(rowCount): \n\(script)\n"
                    }
                    break
                default:
                    break
                    
                  //  return "Unknown operator in row \(rowCount): \n\(script)\n"
                }
            }
        }
        return ""
    }
    
    func closeAllDevices() {
        let numDevices = deviceDescriptors.count
        for i in 0..<numDevices {
            switch (deviceDescriptors[i].deviceType) {
            case 30001:
                (deviceDescriptors[i].deviceClass as! SerialMotorManager).closeManually()
                break
            case 40001:
                
                (deviceDescriptors[i].deviceClass as! TcpIoManager).closeManually()
            default:
                break
            }
        }
    }
    
    func analyzeString(_ input: String) -> [String]? {
        // Find the opening and closing brackets
        guard var openingBracketIndex = input.firstIndex(of: "(") ,
              let closingBracketIndex = input.lastIndex(of: ")") else {
            // Return an error if there are no brackets
            return nil
        }
        // Check if there is any string before the opening bracket
        let stringBeforeBracket = input[..<openingBracketIndex].trimmingCharacters(in: .whitespacesAndNewlines)
        guard !stringBeforeBracket.isEmpty else {
            // Return an error if there is no string before the bracket
            return nil
        }
        
        openingBracketIndex = input.index(after: openingBracketIndex)
        // Extract the values inside the brackets
        let valuesString = input[openingBracketIndex..<closingBracketIndex]
        let values = valuesString
            .trimmingCharacters(in: .whitespacesAndNewlines)
            .components(separatedBy: ",")
            .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
        
        // Create the output array with the string before the bracket followed by the values
        var output = [stringBeforeBracket]
        output.append(contentsOf: values)
        
        // Return the array of values
        return output
    }

}
